package com.ybl.store.backend.service.impl.user;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybl.store.backend.dao.mapper.user.CustomerMapper;
import com.ybl.store.backend.dto.UserInfoDTO;
import com.ybl.store.backend.dto.req.user.customer.CustomerSaveReqDTO;
import com.ybl.store.backend.dto.req.user.customer.CustomerUpdateReqDTO;
import com.ybl.store.backend.dto.resp.user.customer.CustomerNameRespDTO;
import com.ybl.store.backend.dto.resp.user.customer.CustomerPageRespDTO;
import com.ybl.store.backend.service.user.CustomerService;
import com.ybl.store.common.constant.BanFlag;
import com.ybl.store.common.constant.DelFlag;
import com.ybl.store.common.constant.UserPermission;
import com.ybl.store.common.context.UserContext;
import com.ybl.store.common.convention.errorcode.BaseErrorCode;
import com.ybl.store.common.convention.exception.ClientException;
import com.ybl.store.backend.dao.entity.user.CustomerDO;
import com.ybl.store.common.entity.ListRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * 顾客服务层
 */
@Service
@RequiredArgsConstructor
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, CustomerDO> implements CustomerService {

    @Override
    public void saveCustomer(CustomerSaveReqDTO requestParam) {
        checkPermission(requestParam.getClerkId());

        int result = baseMapper.insert(BeanUtil.toBean(requestParam, CustomerDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_SAVE_ERROR);
        }
    }

    @Override
    public void deleteCustomerById(Long id) {
        CustomerDO customerDO = baseMapper.selectById(id);
        if (customerDO == null) {
            throw new ClientException(BaseErrorCode.CUSTOMER_NULL_ERROR);
        }
        checkPermission(customerDO.getClerkId());

        int result = baseMapper.deleteById(id);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_DELETE_ERROR);
        }
    }

    @Override
    public void updateCustomer(CustomerUpdateReqDTO requestParam) {
        checkPermission(requestParam.getClerkId());

        int result = baseMapper.updateById(BeanUtil.toBean(requestParam, CustomerDO.class));
        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_UPDATE_ERROR);
        }
    }

    @Override
    public void banCustomer(Long id, Integer banFlag) {
        CustomerDO customerDO = baseMapper.selectById(id);
        if (customerDO == null) {
            throw new ClientException(BaseErrorCode.CUSTOMER_NULL_ERROR);
        }
        checkPermission(customerDO.getClerkId());

        customerDO = new CustomerDO();
        customerDO.setId(id);
        customerDO.setBanFlag(banFlag);
        int result = baseMapper.updateById(customerDO);
        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_BAN_ERROR);
        }
    }

    @Override
    public ListRespDTO<CustomerPageRespDTO> pageCustomer(Integer pn, Integer ps, Long clerkId, String name) {
        clerkId = checkPermission(clerkId);

        Page<CustomerPageRespDTO> page = new Page<>(pn, ps);
        QueryWrapper<CustomerDO> queryWrapper = Wrappers.query(CustomerDO.class)
                .eq(Objects.nonNull(clerkId), "t_customer.clerk_id", clerkId)
                .like(Objects.nonNull(name), "t_customer.name", name)
                .eq("t_customer.del_flag", 0)
                .orderByAsc("t_customer.name");
        List<CustomerPageRespDTO> customerPageRespDTOList = baseMapper.pageCustomer(page, queryWrapper);

        queryWrapper = Wrappers.query(CustomerDO.class)
                .eq(Objects.nonNull(clerkId), "t_customer.clerk_id", clerkId)
                .like(Objects.nonNull(name), "t_customer.name", name)
                .eq("t_customer.del_flag", 0);
        Long total = baseMapper.selectCount(queryWrapper);

        return ListRespDTO.<CustomerPageRespDTO>builder()
                .total(total)
                .items(customerPageRespDTOList
                        .stream()
                        .map(each -> BeanUtil.toBean(each, CustomerPageRespDTO.class))
                        .toList())
                .build();
    }

    @Override
    public ListRespDTO<CustomerNameRespDTO> listCustomerName(Long clerkId) {
        clerkId = checkPermission(clerkId);

        LambdaQueryWrapper<CustomerDO> lambdaQueryWrapper = Wrappers.lambdaQuery(CustomerDO.class)
                .eq(Objects.nonNull(clerkId), CustomerDO::getClerkId, clerkId)
                .eq(CustomerDO::getDelFlag, DelFlag.present)
                .eq(CustomerDO::getBanFlag, BanFlag.use)
                .orderByAsc(CustomerDO::getName);
        List<CustomerDO> customerDOList = baseMapper.selectList(lambdaQueryWrapper);

        return ListRespDTO.<CustomerNameRespDTO>builder()
                .total((long) customerDOList.size())
                .items(customerDOList
                        .stream()
                        .map(each -> BeanUtil.toBean(each, CustomerNameRespDTO.class))
                        .toList())
                .build();
    }

    private Long checkPermission(Long id) {
        UserInfoDTO userInfoDTO = UserContext.get();
        if (Objects.equals(userInfoDTO.getPermission(), UserPermission.ADMIN)) {
            return id;
        }
        else {
            if (id == null) {
                return userInfoDTO.getId();
            }
            else if (Objects.equals(id, userInfoDTO.getId())) {
                return id;
            }
            else {
                throw new ClientException(BaseErrorCode.CLIENT_UNAUTHORIZED_ERROR);
            }
        }
    }
}
